﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using RabbitMQ.Client.Framing.Impl;
using ZL.Web.Utility.Config;
using ZLWeb.WebApiEntityBase;

namespace ZL.Web.Utility.Mongodb
{
    public class MongoHelper<T> where T : MongoModel
    {
        public string conn;
        public string dbName;
        public string collectionName;

        private MongoCollection<T> collection;

        //static MongoHelper<T>.Builder<T> builder { get; set; }
        private MongoHelper()
        {
           
        }

        public static MongoHelper<T> GetMongoClient(string mongodb_dbName, string collectionname)
        {
            var builder = new MongoHelper<T>.Builder<T>();
            builder.setCollectionName(collectionname);
            builder.setConn(string.Format("mongodb://{0}/?safe=true", ZLConfig.Mongodbserver));
            builder.setDbName(mongodb_dbName);
            var client = builder.build();
            return client;
        }

        /// <summary>
        /// 设置你的collection
        /// </summary>
        public void SetCollection()
        {
            MongoClient client = new MongoClient(conn);
            var server = client.GetServer();
            var database = server.GetDatabase(dbName);
            collection = database.GetCollection<T>(collectionName);
        }

        /// <summary>
        /// 你用linq的时候会用到
        /// </summary>
        public void getCollection()
        {
            MongoClient client = new MongoClient(conn);
            var server = client.GetServer();
            var database = server.GetDatabase(dbName);
            collection = database.GetCollection<T>(collectionName);
        }

        /// <summary>
        /// 查找
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public T Find(IMongoQuery query)
        {
            return this.collection.FindOne(query);
        }


        /// <summary>
        /// 查找
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public MongoCursor<T> FindAll(IMongoQuery query)
        {
            MongoCursor <T> ts= this.collection.Find(query);
            return ts;
        }

        /**
         * 条件查询用linq
         * http://mongodb.github.io/mongo-csharp-driver/1.11/linq/
         * */
        public List<T> FindAll()
        {
            return this.collection.FindAll().ToList();
           // Model.AccountModel res = client.Find(MongoDB.Driver.Builders.Query<Model.AccountModel>.EQ(xx => xx.id, account.id));
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public long Update(T model)
        {
            model.updated_at = new BsonDateTime(DateTime.Now);
            BsonDocument doc = BsonExtensionMethods.ToBsonDocument(model);
            WriteConcernResult res = this.collection.Update(Query.EQ("_id", model.id), new UpdateDocument(doc));
            return res.DocumentsAffected;
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool Insert(T model)
        {
            model.created_at = new BsonDateTime(DateTime.Now);
            model.updated_at = new BsonDateTime(DateTime.Now);
            WriteConcernResult res = this.collection.Insert(model);
            return (!res.HasLastErrorMessage);
            //return res.Upserted.AsBoolean;
        }
        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool InsertWithexpire(T model, TimeSpan expire)
        {
            model.created_at = new BsonDateTime(DateTime.Now);
            model.updated_at = new BsonDateTime(DateTime.Now);
            var keys = IndexKeys.Descending("updated_at");
            var options = IndexOptions.SetTimeToLive(expire);
            collection.CreateIndex(keys, options);
            WriteConcernResult res = this.collection.Insert(model);
            return (!res.HasLastErrorMessage);
            //return res.Upserted.AsBoolean;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool Delete(T model)
        {
            WriteConcernResult res = this.collection.Remove(Query.EQ("_id", model.id));
            return res.DocumentsAffected>0;
        }

        /// <summary>
        /// 构造器
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class Builder<T> where T : MongoModel
        {
            private MongoHelper<T> client;

            public Builder()
            {
                client = new MongoHelper<T>();
            }

            public void setConn(string conn)
            {
                client.conn = conn;
            }

            public void setDbName(string dbName)
            {
                client.dbName = dbName;
            }

            public void setCollectionName(string collectionName)
            {
                client.collectionName = collectionName;
            }

            public MongoHelper<T> build()
            {
                client.SetCollection();
                return client;
            }
        }
    }
}
